Helper.using('py.Figures', function (ns) {
    ns.Point = function (params) {
        ns.Figure.call(this, params);
        this.setType('Point');

        this.visual(new Kinetic.Circle({
            radius:5, strokeWidth:2,
            fill:'red', stroke:'black',
            draggable:false
        }));

        this.getX = function () {
        };
        this.getY = function () {
        };
        this.getPosition = function () {
            return {
                x:this.getX(), y:this.getY()
            }
        }

        this.update = function (viewPort) {
            var unit = {x:this.getX(), y:this.getY()},
                pixel = viewPort.getPixelPoint(unit),
                visual = this.visual(),
                layer = visual.getLayer();

            visual.setX(pixel.x);
            visual.setY(pixel.y);
            visual.moveToTop();
            layer && layer.moveToTop();

        };

        this.toString = function () {
            return 'Point: {x:' + this.getX() + ' y:' + this.getY() + '}';
        };
    };

    // static methods
    ns.Point.distance = function (p1, p2) {
        var dx = p1.getX() - p2.getX(),
            dy = p1.getY() - p2.getY();

        return Math.sqrt(dx * dx + dy * dy);
    }

    // return square of distance of two points
    ns.Point.distanceR = function (p1, p2) {
        var dx = p1.getX() - p2.getX(),
            dy = p1.getY() - p2.getY();

        return dx * dx + dy * dy;

    }

    // Point subclass

    ns.PointXY = function (params) {
        ns.Point.call(this, params);
        ns.Movable.call(this, params);

        this.setType('PointXY');

        params = Helper.extend({
            x:NaN, y:NaN
        }, params);

        var _x = params.x, _y = params.y;

        this.formed = function () {
            return !isNaN(_x) && !isNaN(_y);
        };

        this.getX = function () {
            return _x;
        };
        this.getY = function () {
            return _y;
        };

        this.setX = function (x) {
            _x = x;
        };
        this.setY = function (y) {
            _y = y;
        };
    };

    ns.MidPoint = function (params) {
        ns.Point.call(this, params);
        ns.DependentObject.call(this);
        this.setType('MidPoint');

        params = Helper.extend({
            ends:[]
        }, params);

        this.formed = function () {
            return params.ends.length == 2;
        };

        this.getX = function () {
            var _a = params.ends[0], _b = params.ends[1];
            return (_a.getX() + _b.getX()) / 2;
        };

        this.getY = function () {
            var _a = params.ends[0], _b = params.ends[1];
            return (_a.getY() + _b.getY()) / 2;
        };

        this.setEnds = function(ends) {
            params.ends = ends;
        };

        this.setEnd = function(index, end) {
            params.ends[index] = end;
        };

    };

    /*
     * intersection of two lines
     * Just use simple formula copy from wikipedia :
     * -----http://en.wikipedia.org/wiki/Line-line_intersection-----
     */
    ns.Intersection = function (params) {
        ns.Point.call(this, params);
        this.setType('Intersection');

        /*if (!params || !params.lines || params.lines.length!=2){
            throw new Error('Wrong Parameter');
        }*/

        params = Helper.extend({
            lines:null
        }, params);

        var l1, l2, x1, x2, x3, x4, y1, y2, y3, y4;
        var denominator, Px, Py;

        var initialize = function(){
            // two line
            l1 = params.lines[0];
            l2 = params.lines[1];

            // normalize to wikipedia

            x1 = l1.getAnchor().getX();
            y1 = l1.getAnchor().getY();
            x2 = x1 + l1.getDirectionVector().getX();
            y2 = y1 + l1.getDirectionVector().getY();

            x3 = l2.getAnchor().getX();
            y3 = l2.getAnchor().getY();
            x4 = x3 + l2.getDirectionVector().getX();
            y4 = y3 + l2.getDirectionVector().getY();

            /* denominator : the denominator of formula  : both x and y coord has same */
            denominator = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
            /* denominator == 0 ? parallel or coincident */
            if (denominator == 0) {
                Px = null;
                Py = null;
                return;
            }
            /* Intersection of two lines has coordinate P(x,y) */
            Px = ((x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4)) / denominator;
            Py = ((x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4)) / denominator;
        };

        initialize();

        this.getX = function () {
            return Px;
        };

        this.getY = function () {
            return Py;
        };

        this.getPoint = function () {
            return {
                x:Px, y:Py
            }
        };

        this.setLines = function(lines){
            params.lines = lines;
            initialize();
        }
    };

    ns.Center = function (params){
        ns.Point.call(this, params);
        this.setType('Center');


        /*if (!params || !params.circle ){
         throw new Error('Wrong Parameter');
         }*/

        params = Helper.extend({
            circle:null
        }, params);

        this.getX = function () {
            return params.circle.getCenter().getX();
        };

        this.getY = function () {
            return params.circle.getCenter().getY();
        };


        this.getCircle = function(circle){
            params.circle = circle;
        };

    }

    ns.PointOnLinear = function (params){
        ns.Point.call(this, params);
        this.setType('PointOnLinear');

        /*if (!params || !params.initial || !params.linear ){
         throw new Error('Wrong Parameter');
         }*/

        params = Helper.extend({
            initial:null,
            linear : null
        }, params);

        var point, linearObject, anchor, vector, pointVector;

        point = params.initial;
        linearObject = params.linear;
        anchor = linearObject.getAnchor();
        vector = linearObject.getDirectionVector();
        // debug
        //anchor = linearObject.anchor;
        //vector = linearObject.vector;

        if (point.getX()==anchor.getX() && point.getY()==anchor.getY()){
            return true;
        }

        pointVector = new ns.Vector2Point({head:point, tail:anchor});
        if ( vector.getX()*pointVector.getY() == vector.getY()*pointVector.getX()){
            return true;
        }
        else{
            return false;
        }







    }


});

